package com.mason.forum.service.impl;

import com.mason.forum.common.ResultCode;
import com.mason.forum.dao.UserMapper;
import com.mason.forum.exception.ApplicationException;
import com.mason.forum.model.User;
import com.mason.forum.service.IUserService;
import com.mason.forum.utils.MD5Utils;
import com.mason.forum.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 马拉圈
 * Date: 2023-10-05
 * Time: 18:21
 */
@Slf4j
@Service
public class UserServiceImpl implements IUserService {
//IUserService不加注解，因为它自己不能实例化，应该注入其实现类，也就是说其实现类UserServiceImpl要加注解
// 并且要避免冲突，这样框架就会注入唯一的那个实现这个接口的bean给这个IUserService对象

    @Resource
    private UserMapper userMapper;

    //创建普通用户对象，方法实现
    @Override
    public void  createNormalUser(User user) {
        // 0. 非空校验
        if(user == null ||
                !StringUtils.hasLength(user.getUsername(), user.getPassword(), user.getNickname())) {
            // 0.1 打印异常日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            // 0.2 抛出异常
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
            //直接抛异常有个好处，就是这样就不用刻意去区分这个方法的返回值，而是一个确切含义的返回值，而不是（1. 异常 2. 正常数据 3. ...）
            //抛出来的话：事务可以会滚、调用者controller会被异常处理器捕获~
        }
        // 1. 用户名查询是否已存在
        User userSelectByUsername = userMapper.selectByUsername(user.getUsername());
        if(userSelectByUsername != null) {
            // 1.1 打印异常日志
            log.info(ResultCode.AILED_USER_EXISTS.toString());
            // 1.2 抛出异常
            throw new ApplicationException(ResultCode.AILED_USER_EXISTS);
        }
        // 2. 加盐加密
        String salt = MD5Utils.getSalt();
        String plusPassword =  MD5Utils.encrypt(salt, user.getPassword());
        user.setSalt(salt);
        user.setPassword(plusPassword);
        // 3. 设置一些默认值（以免通过postman等工具，通过构造信息的方式自己设置信息！）
            // 或者说这些事情可以在这里做，少给数据库一点负担
        user.setGender((byte) 2);
        user.setArticleCount(0);
        user.setIsAdmin((byte) 0);
        user.setState((byte) 0);
        user.setDeleteState((byte) 0);
        Date date = new Date();
        user.setCreateTime(date);
        user.setUpdateTime(date);

        // 3. 注册普通用户
        int rows = userMapper.insertSelective(user);
        // 4. 是否注册成功
        if(rows != 1) {
            // 4.1 打印异常日志
            log.info(ResultCode.FAILED_CREATE.toString());
            // 4.2 抛出异常
            throw new ApplicationException(ResultCode.FAILED_CREATE);
        }
        // 5. 新增成功，over...
        log.info(ResultCode.SUCCESS.toString() + "新增成功: username: "
            + user.getUsername() + ". ");
    }

    @Override
    public User selectByUsername(String username) {
        if(!StringUtils.hasLength(username)) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        return userMapper.selectByUsername(username);
    }

    @Override
    public User login(String username, String password) {
        // 1. 校验参数
        if(!StringUtils.hasLength(username, password)) {//每次都非空校验，防止别人没处理却调用你的代码，利于团队合作...
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        // 2. 根据用户名查询用户信息
        User user = selectByUsername(username);
        if(user == null) {
            log.info(ResultCode.FAILED_LOGIN.toString() + "[用户名错误] username: "
                    + username + ". ");
            throw new ApplicationException(ResultCode.FAILED_LOGIN);
        }
        // 3. 验证密码
        String salt = user.getSalt();
        String db_Password = user.getPassword();
        if(MD5Utils.confirm(salt, password, db_Password)) {
            // 登录成功
            log.info(ResultCode.SUCCESS.toString() + "登录成功: username: "
                    + user.getUsername() + ". ");
            return user;
        }else {
            // 登录失败
            log.info(ResultCode.FAILED_LOGIN.toString() + "[密码错误] username: "
                    + username + ". ");
            throw new ApplicationException(ResultCode.FAILED_LOGIN);
        }
    }

    @Override
    public User selectById(Long id) {

        // 0. 非空校验
        if(id == null) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        // 1. 调用dao
        User user = userMapper.selectByPrimaryKey(id);
        if(user == null) {
            log.info(ResultCode.FAILED_USER_NOT_EXISTS.toString() + "[用户不存在] id: "
                    + id + ". ");
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        // 2. 返回结果
        return user;
    }


    @Override
    public void incrementArticleCountById(Long id) {
        // 1. 参数校验
        if(id == null || id <= 0) {
            log.warn(ResultCode.FAILED_USER_ARTICLE_COUNT.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_ARTICLE_COUNT);
        }
        // 2. 调用dao层
        User user = userMapper.selectByPrimaryKey(id);
        if(user == null || user.getDeleteState() == 1) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        if(user.getState() == 1) {
            log.warn(ResultCode.FAILED_USER_BANNED.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_BANNED);
        }
        User updateUser = new User();
        updateUser.setArticleCount(user.getArticleCount() + 1);
        updateUser.setId(id);
        int rows = userMapper.updateByPrimaryKeySelective(updateUser);//更新一个值就够了
        if(rows != 1) {
            log.warn(ResultCode.FAILED_USER_ARTICLE_COUNT.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_ARTICLE_COUNT);
        }
        // 更新成功
        log.info(ResultCode.SUCCESS.toString() + "更新成功: user id: "
                + id + ". ");
    }

    @Override
    public void decrementArticleCountById(Long id) {
        // 1. 参数校验
        if(id == null || id <= 0) {
            log.warn(ResultCode.FAILED_USER_ARTICLE_COUNT.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_ARTICLE_COUNT);
        }
        // 2. 调用dao层
        User user = userMapper.selectByPrimaryKey(id);
        if(user == null || user.getDeleteState() == 1) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        if(user.getState() == 1) {//此状态无法做出修改的如何事情
            log.warn(ResultCode.FAILED_USER_BANNED.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_BANNED);
        }
        User updateUser = new User();
        int count = user.getArticleCount() - 1;
        updateUser.setArticleCount(Math.max(count, 0));
        updateUser.setId(id);
        int rows = userMapper.updateByPrimaryKeySelective(updateUser);//更新一个值就够了
        if(rows != 1) {
            log.warn(ResultCode.FAILED_USER_ARTICLE_COUNT.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_ARTICLE_COUNT);
        }
        // 更新成功
        log.info(ResultCode.SUCCESS.toString() + "更新成功: user id: "
                + id + ". ");
    }


    @Override
    public void updateUserInfo(User user) {
        // 非空校验
        if(user == null || user.getId() == null || user.getId() <= 0) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        // user必须存在且有效
        Long id = user.getId();
        User existsUser = userMapper.selectByPrimaryKey(id);
        if(existsUser == null || existsUser.getDeleteState() == 1) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        if(existsUser.getState() == 1) {//此状态无法做出修改的如何事情
            log.warn(ResultCode.FAILED_USER_BANNED.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_BANNED);
        }
        // 定义一个标志位
        boolean checkAttr = false;//等一下如果每一个都不修改（都为null），就仍然是false，表示校验不通过
        // 对每一个参数进行校验并且生成一个专门用来更新的对象（密码不在这里处理）
        User updateUser = new User();
        updateUser.setId(id);//设置id
        updateUser.setUpdateTime(new Date());
        // ====== 校验用户名 ======
        String username = user.getUsername();
        if(StringUtils.hasLength(username)
                && !existsUser.getUsername().equals(username)) {
            //进行用户名唯一性校验
            User userByUsername = userMapper.selectByUsername(username);
            if(userByUsername == null) {
                checkAttr = true;
                updateUser.setUsername(username);
            }else if(!username.equals(existsUser.getUsername())) { //如果没有修改，则不需要抛出这个异常
                log.info(ResultCode.AILED_USER_EXISTS.toString());
                throw new ApplicationException(ResultCode.AILED_USER_EXISTS);
            }
        }
        // ====== 校验昵称 ======
        String nickname = user.getNickname();
        if(StringUtils.hasLength(nickname)
                && !existsUser.getNickname().equals(nickname)) {
            checkAttr = true;
            updateUser.setNickname(nickname);
        }
        // ====== 校验性别 ======
        Byte gender = user.getGender();
        if(gender != null
                && !gender.equals(existsUser.getGender())) {
            checkAttr = true;
            if(gender > 2 || gender < 0) {
                gender = 2;
            }
            updateUser.setGender(gender);
        }
        // ====== 校验邮箱 ======
        String email = user.getEmail();
        if(StringUtils.hasLength(email)
                && !email.equals(existsUser.getEmail())) {
            checkAttr = true;
            updateUser.setEmail(email);
        }
        // ====== 校验电话号码 ======
        String phoneNum = user.getPhoneNum();
        if(StringUtils.hasLength(phoneNum)
                && !phoneNum.equals(existsUser.getPhoneNum())) {
            checkAttr = true;
            updateUser.setPhoneNum(phoneNum);
        }
        // ====== 校验简介 ======
        String remark = user.getRemark();
        if(StringUtils.hasLength(remark)
                && !remark.equals(existsUser.getRemark())) {
            checkAttr = true;
            updateUser.setRemark(remark);
        }
        // 如果一个都没修改，则代表与原数据一致
        if(!checkAttr) {
            log.warn(ResultCode.FAILED_UPDATE_USER_INFO_COMMON.toString());
            throw new ApplicationException(ResultCode.FAILED_UPDATE_USER_INFO_COMMON);
        }
        // 更新用户信息
        int rows = userMapper.updateByPrimaryKeySelective(updateUser);
        if(rows != 1) {
            log.warn(ResultCode.FAILED_UPDATE_USER_INFO.toString());
            throw new ApplicationException(ResultCode.FAILED_UPDATE_USER_INFO);
        }
        // 更新成功
        log.info(ResultCode.SUCCESS.toString() + "更新成功: user id: "
                + id + ". ");
    }

    @Override
    public void modifyUserPassword(Long id, String password, String oldPassword) {
        // 参数校验
        if(id == null || id <= 0 || !StringUtils.hasLength(password, oldPassword)) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        if(password.equals(oldPassword)) {
            log.warn(ResultCode.FAILED_UPDATE_USER_INFO_COMMON.toString());
            throw new ApplicationException(ResultCode.FAILED_UPDATE_USER_INFO_COMMON);
        }
        // user必须存在且有效
        User existsUser = userMapper.selectByPrimaryKey(id);
        if(existsUser == null || existsUser.getDeleteState() == 1) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        if(existsUser.getState() == 1) {//此状态无法做出修改的如何事情
            log.warn(ResultCode.FAILED_USER_BANNED.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_BANNED);
        }
        // 验证老密码
        String oldSalt = existsUser.getSalt();
        if(!MD5Utils.confirm(oldSalt, oldPassword, existsUser.getPassword())) {
            // 原密码错误
            log.warn(ResultCode.FAILED_USER_PASSWORD.toString() + " user id：" + id);
            throw new ApplicationException(ResultCode.FAILED_USER_PASSWORD);
        }
        // 构造新的加盐加密密码
        String newSalt = MD5Utils.getSalt();
        String newPlusPassword = MD5Utils.encrypt(newSalt, password);
        // 构造去更新用户的用户对象
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setPassword(newPlusPassword);
        updateUser.setSalt(newSalt);
        updateUser.setUpdateTime(new Date());
        // 更新用户消息
        int rows = userMapper.updateByPrimaryKeySelective(updateUser);
        if(rows != 1) {
            log.warn(ResultCode.FAILED_UPDATE_USER_PASSWORD.toString());
            throw new ApplicationException(ResultCode.FAILED_UPDATE_USER_PASSWORD);
        }
        // 更新成功
        log.info(ResultCode.SUCCESS.toString() + "更新成功: user id: "
                + id + ". ");
    }


}
